﻿using System;
using System.Windows.Forms;
using System.Diagnostics;
using Utilities;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Collections.Generic;

namespace NumPadSnap
{
    public partial class Form1 : Form
    {
        private NotifyIcon trayIcon;
        private ContextMenu trayMenu;

        globalKeyboardHook gkh;
        Rectangle screenSize;
        Point mousePos;
        Dictionary<Keys, bool> keyStates;

        static readonly IntPtr HWND_TOP = new IntPtr(0);

        int screenTop;
        int screenBottom;
        int screenLeft;
        int screenRight;

        int screenX0;
        int screenX1;
        int screenX2;
        int screenX3;
        int screenY0;
        int screenY1;
        int screenY2;
        int screenY3;


        public Form1()
        {
            trayMenu = new ContextMenu();
            trayMenu.MenuItems.Add("Exit", OnExit);

            trayIcon = new NotifyIcon();
            trayIcon.Text = "NumPadSnap";
            trayIcon.Icon = new Icon(SystemIcons.Application, 40, 40);

            trayIcon.ContextMenu = trayMenu;
            trayIcon.Visible = true;
            
            InitializeComponent();
        }

        protected override void OnLoad(EventArgs e)
        {
            Visible = false;
            ShowInTaskbar = false;
            
            base.OnLoad(e);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            gkh = new globalKeyboardHook();
            keyStates = new Dictionary<Keys, bool>();

            initKeyStates(ref keyStates);

            //screenSize = GetScreen();
            screenSize = Screen.PrimaryScreen.WorkingArea;

            screenTop = screenSize.Top;
            screenBottom = screenSize.Bottom;
            screenLeft = screenSize.Left;
            screenRight = screenSize.Right;

            screenX0 = screenLeft;
            screenX1 = screenLeft + (1 * ((screenRight - screenLeft) / 3));
            screenX2 = screenLeft + (2 * ((screenRight - screenLeft) / 3));
            screenX3 = screenRight;

            screenY0 = screenTop;
            screenY1 = screenTop + (1 * ((screenBottom - screenTop) / 3));
            screenY2 = screenTop + (2 * ((screenBottom - screenTop) / 3));
            screenY3 = screenBottom;

            Debug.WriteLine(screenX0);
            Debug.WriteLine(screenX1);
            Debug.WriteLine(screenX2);
            Debug.WriteLine(screenX3);
            Debug.WriteLine(screenY0);
            Debug.WriteLine(screenY1);
            Debug.WriteLine(screenY2);
            Debug.WriteLine(screenY3);
            

            gkh.HookedKeys.Add(Keys.NumPad1);
            gkh.HookedKeys.Add(Keys.NumPad2);
            gkh.HookedKeys.Add(Keys.NumPad3);
            gkh.HookedKeys.Add(Keys.NumPad4);
            gkh.HookedKeys.Add(Keys.NumPad5);
            gkh.HookedKeys.Add(Keys.NumPad6);
            gkh.HookedKeys.Add(Keys.NumPad7);
            gkh.HookedKeys.Add(Keys.NumPad8);
            gkh.HookedKeys.Add(Keys.NumPad9);
            gkh.KeyDown += new KeyEventHandler(gkh_KeyDown);
            gkh.KeyUp += new KeyEventHandler(gkh_KeyUp);
        }

        private void gkh_KeyUp(object sender, KeyEventArgs e)
        {
            bool windowDragging;
            bool keyPressed;
            bool keyFound;
            NativeMethods.RECT rect;
            IntPtr foregroundWindow;

            keyFound = keyStates.TryGetValue(e.KeyCode, out keyPressed);

            Debug.WriteLine("key pressed:" + e.KeyCode.ToString());
            Debug.WriteLine("key found:" + keyFound.ToString());
            Debug.WriteLine("key pressed:" + keyPressed.ToString());

            if (keyFound && keyPressed)
            {
                keyStates[e.KeyCode] = false;
                Debug.WriteLine("SET FALSE");
            }

            Rectangle newWindowSize = getNewWindowSize();

            int winTop = newWindowSize.Top;
            int winLeft = newWindowSize.Left;
            int winWidth = newWindowSize.Width;
            int winHeight = newWindowSize.Height;

            Debug.WriteLine("Top: " + winTop + " Left: " + winLeft + " Width: " + winWidth + " Height: " + winHeight);

            //mousePos = Control.MousePosition;
            //rect = new NativeMethods.RECT();
            //foregroundWindow = NativeMethods.GetForegroundWindow();

            //if (NativeMethods.GetWindowRect(foregroundWindow, ref rect))
            //{
            //    windowDragging = Control.MouseButtons.Equals(MouseButtons.Left) && mousePos.X >= rect.Left
            //        && mousePos.X <= rect.Right && mousePos.Y >= rect.Top && mousePos.Y <= rect.Top + 40;

            //    if (windowDragging)
            //    {
                    //NativeMethods.SetWindowPos(
                    //    foregroundWindow,
                    //    HWND_TOP,
                    //    winTop,
                    //    winLeft,
                    //    winBottom,
                    //    winRight,
                    //    0);
            //    }
            //}

            e.Handled = true;
        }

        private void gkh_KeyDown(object sender, KeyEventArgs e)
        {
            bool windowDragging;
            bool keyPressed;
            bool keyFound;
            NativeMethods.RECT rect;
            IntPtr foregroundWindow;

            keyFound = keyStates.TryGetValue(e.KeyCode, out keyPressed);

            Debug.WriteLine("key pressed:" + e.KeyCode.ToString());
            Debug.WriteLine("key found:" + keyFound.ToString());
            Debug.WriteLine("key pressed:" + keyPressed.ToString());

            if(keyFound && !keyPressed)
            {
                keyStates[e.KeyCode] = true;
                Debug.WriteLine("SET TRUE");
            }

            Rectangle newWindowSize = getNewWindowSize();

            int winTop = newWindowSize.Top;
            int winLeft = newWindowSize.Left;
            int winWidth = newWindowSize.Width;
            int winHeight = newWindowSize.Height;

            Debug.WriteLine("Top: " + winTop + " Left: " + winLeft + " Width: " + winWidth + " Height: " + winHeight);

            //mousePos = Control.MousePosition;
            //rect = new NativeMethods.RECT();
            foregroundWindow = NativeMethods.GetForegroundWindow();

            //if (NativeMethods.GetWindowRect(foregroundWindow, ref rect))
            //{
            //    windowDragging = Control.MouseButtons.Equals(MouseButtons.Left) && mousePos.X >= rect.Left 
            //        && mousePos.X <= rect.Right && mousePos.Y >= rect.Top && mousePos.Y <= rect.Top+40;

            //    if (windowDragging)
            //    {
                        NativeMethods.SetWindowPos(
                            foregroundWindow,
                            HWND_TOP,
                            winLeft,
                            winTop,
                            winWidth,
                            winHeight,
                            0);
            //    }
            //}

            e.Handled = true;
        }

        private Rectangle GetScreen()
        {
            return Screen.FromControl(this).Bounds;
        }

        private void initKeyStates(ref Dictionary<Keys, bool> refDic)
        {
            refDic.Add(Keys.NumPad1, false);
            refDic.Add(Keys.NumPad2, false);
            refDic.Add(Keys.NumPad3, false);
            refDic.Add(Keys.NumPad4, false);
            refDic.Add(Keys.NumPad5, false);
            refDic.Add(Keys.NumPad6, false);
            refDic.Add(Keys.NumPad7, false);
            refDic.Add(Keys.NumPad8, false);
            refDic.Add(Keys.NumPad9, false);
        }

        private Rectangle getNewWindowSize()
        {
            //Get X Min
            int? xMin = null;
            int? xMax = null;
            int? yMin = null;
            int? yMax = null;

            int xMinPixel = 0;
            int xMaxPixel = 0;
            int yMinPixel = 0;
            int yMaxPixel = 0;

            bool[,] posPressed = new bool[3, 3];

            bool success;

            success = keyStates.TryGetValue(Keys.NumPad1, out posPressed[0, 0]);
            success = keyStates.TryGetValue(Keys.NumPad2, out posPressed[1, 0]);
            success = keyStates.TryGetValue(Keys.NumPad3, out posPressed[2, 0]);
            success = keyStates.TryGetValue(Keys.NumPad4, out posPressed[0, 1]);
            success = keyStates.TryGetValue(Keys.NumPad5, out posPressed[1, 1]);
            success = keyStates.TryGetValue(Keys.NumPad6, out posPressed[2, 1]);
            success = keyStates.TryGetValue(Keys.NumPad7, out posPressed[0, 2]);
            success = keyStates.TryGetValue(Keys.NumPad8, out posPressed[1, 2]);
            success = keyStates.TryGetValue(Keys.NumPad9, out posPressed[2, 2]);

            //GET X MIN
            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    if (posPressed[i, j])
                    {
                        xMin = i;
                        break;
                    }
                }

                if (xMin.HasValue)
                {
                    break;
                }
            }

            //GET X MAX
            for (int i = 2; i >= 0; i--)
            {
                for (int j = 0; j < 3; j++)
                {
                    if (posPressed[i, j])
                    {
                        xMax = i;
                        break;
                    }
                }

                if (xMax.HasValue)
                {
                    break;
                }
            }

            //GET Y MIN
            for (int j = 0; j < 3; j++)
            {
                for (int i = 0; i < 3; i++)
                {
                    if (posPressed[i, j])
                    {
                        yMax = j;
                        break;
                    }
                }

                if (yMax.HasValue)
                {
                    break;
                }
            }

            //GET Y MAX
            for (int j = 2; j >= 0; j--)
            {
                for (int i = 0; i < 3; i++)
                {
                    if (posPressed[i, j])
                    {
                        yMin = j;
                        break;
                    }
                }

                if (yMin.HasValue)
                {
                    break;
                }
            }

            switch (xMin)
            {
                case 0:
                    xMinPixel = screenX0;
                    break;
                case 1:
                    xMinPixel = screenX1;
                    break;
                case 2:
                    xMinPixel = screenX2;
                    break;
            }

            switch (xMax)
            {
                case 0:
                    xMaxPixel = screenX1;
                    break;
                case 1:
                    xMaxPixel = screenX2;
                    break;
                case 2:
                    xMaxPixel = screenX3;
                    break;
            }

            switch (yMin)
            {
                case 0:
                    yMinPixel = screenY2;
                    break;
                case 1:
                    yMinPixel = screenY1;
                    break;
                case 2:
                    yMinPixel = screenY0;
                    break;
            }

            switch (yMax)
            {
                case 0:
                    yMaxPixel = screenY3;
                    break;
                case 1:
                    yMaxPixel = screenY2;
                    break;
                case 2:
                    yMaxPixel = screenY1;
                    break;
            }

            Debug.WriteLine("xMin: " + xMin + " xMax: " + xMax + " yMin: " + yMin + " yMax: " + yMax);

            return new Rectangle(xMinPixel, yMinPixel, (xMaxPixel - xMinPixel), (yMaxPixel - yMinPixel));

        }

        private void OnExit(object sender, EventArgs e)
        {
            Application.Exit();
        }

        protected override void Dispose(bool isDisposing)
        {
            if (isDisposing)
            {
                trayIcon.Dispose();
            }
            base.Dispose(isDisposing);
        }

            

    }

    class NativeMethods
    {
        [DllImport("user32.dll")]
        public static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll")]
        public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X,
            int Y, int cx, int cy, uint uFlags);

        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);

        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }
    }
}
